#pragma comment(lib, "lib\\SDL.lib")
#pragma comment(lib, "lib\\SDLmain.lib")
#include "include\SDL.h"
#include <windows.h>
#include "renderer.h"
#include <stdexcept>
#include <list>
#include <math.h>
#include "object.h"
#include "input.h"
#include "map.h"
using namespace std;
bool quit=false;
list<event_class>* events_list;
list<gameobject>* objects_list;
renderer* gameRenderer;
map* current_map;
int xScr=-1, yScr=-1;
int xLeft=-1, yLeft=-1;
bool leftDown=false;

void process_event(void) {
	list<event_class>::iterator events_iterator;
	for (events_iterator = events_list->begin(); events_iterator != events_list->end(); events_iterator++){
		switch(events_iterator->type) {

			case SDL_KEYDOWN: 
				if(events_iterator->key == SDLK_ESCAPE) 
					quit=true;
				break;

			case SDL_QUIT:
				quit=true;
				break;

			case SDL_MOUSEBUTTONDOWN: 
				if(events_iterator->button == SDL_BUTTON_RIGHT){
					std::list<gameobject>::iterator object_iterator;
					for (object_iterator = objects_list->begin(); object_iterator != objects_list->end(); object_iterator++) {
						if(object_iterator->controlled)
						{
							SDL_GetMouseState( &xScr, &yScr ); 
							object_iterator->destX=gameRenderer->XScrToMap(xScr);
							object_iterator->destY=gameRenderer->YScrToMap(yScr); 
						}
					}

				}
				if(events_iterator->button == SDL_BUTTON_LEFT){
					SDL_GetMouseState( &xLeft, &yLeft ); 
					leftDown=true;
				}
				break;

			case SDL_MOUSEBUTTONUP:
				if(events_iterator->button==SDL_BUTTON_LEFT)
					leftDown=false;
				break;

			default:
				break;
		}
	}  
}

void ProcessSelection( int xLeft, int yLeft, int xLeftNow, int yLeftNow ) 
{
	
	std::list<gameobject>::iterator object_iterator;
	for (object_iterator = objects_list->begin(); object_iterator != objects_list->end(); object_iterator++) 
	{
		int x=gameRenderer->XMapToScr((int)object_iterator->x);
		if((x>xLeft&&x<xLeftNow)||(x<xLeft&&x>xLeftNow)) 
			object_iterator->controlled=true;
		else object_iterator->controlled=false;
	}
}

void game_update( double t, const Uint32 dt ) 
{
	static int x=0;
	Uint8 *keys=SDL_GetKeyState(NULL);
	if(keys[SDLK_RIGHT]) 
	{
		if(current_map->size - gameRenderer->screenWidthCells - gameRenderer->gameCamera.xCamera > 5) gameRenderer->gameCamera.xCamera += 5;
		else gameRenderer->gameCamera.xCamera = current_map->size-gameRenderer->screenWidthCells;
	}
	if(keys[SDLK_LEFT])
	{
		if(gameRenderer->gameCamera.xCamera > 5) gameRenderer->gameCamera.xCamera-=5;
		else gameRenderer->gameCamera.xCamera=0;
	}
	if(keys[SDLK_UP])
	{
		if(gameRenderer->gameCamera.yCamera>5) gameRenderer->gameCamera.yCamera-=5;
		else gameRenderer->gameCamera.yCamera=0;
	}
	if(keys[SDLK_DOWN])
	{
		if(current_map->size - gameRenderer->screenHeightCells - gameRenderer->gameCamera.yCamera > 5) gameRenderer->gameCamera.yCamera+=5;
		else gameRenderer->gameCamera.yCamera = current_map->size - gameRenderer->screenHeightCells;
	}   
	int xLeftNow,yLeftNow;
	SDL_GetMouseState(&xLeftNow,&yLeftNow);
	if(leftDown) 
	{
		gameRenderer->DrawRectangle(min(xLeft,xLeftNow),min(yLeft,yLeftNow),abs(xLeftNow-xLeft),abs(yLeftNow-yLeft), 0xffffff);
		gameRenderer->shouldDrawGrasp=true;
	}
	else
	{
		if(gameRenderer->shouldDrawGrasp) 
			ProcessSelection(xLeft, yLeft, xLeftNow, yLeftNow);
		gameRenderer->shouldDrawGrasp=false;
	}
	std::list<gameobject>::iterator object_iterator;
	for (object_iterator = objects_list->begin(); object_iterator != objects_list->end(); object_iterator++) 
	{
		if(object_iterator->controlled)
		{
			if(object_iterator->x!=object_iterator->destX && object_iterator->y!=object_iterator->destY)
			{
				long double cathX=(long double) object_iterator->x - object_iterator->destX;
				long double cathY=(long double) object_iterator->y - object_iterator->destY;
				long double hypo=sqrt(cathX*cathX+cathY*cathY);
				long double csnA=cathX / hypo;
				long double sinA=cathY / hypo;
				if(hypo > dt * object_iterator->speed)
				{
					object_iterator->x -= dt * object_iterator->speed * csnA;
					object_iterator->y -= dt * object_iterator->speed * sinA;
				}
				else
				{
					object_iterator->x = object_iterator->destX;
					object_iterator->y = object_iterator->destY;
				}
			}
		}
	}

}

void game_init(list<gameobject>* objects_list) 
{
	/*
	gameobject* ball=new gameobject(0, 0, "ball.bmp", 0x000000, true, 50, 50, 0, 0, true, true, 1);
	gameObjects->push_front(*ball);
	gameobject* marbles=new gameobject(100,100,"marbles.bmp", 0x000000, true, 100,100,0,0,false,false,1);
	gameObjects->push_front(*marbles);
		*/
	/*
	map *temp=new map();
	temp->Generate("maps\\map1");
	*/

	current_map=new map("maps\\map1");
	gameobject* elf1=new gameobject(100, 100, "elf.bmp", 0xfcfcfc, true, 35, 41, 100, 100, true, true, 0.5);
	objects_list->push_front(*elf1);
	gameobject* elf2=new gameobject(500, 300, "elf.bmp", 0xfcfcfc, true, 35, 41, 500, 300, true, false, 0.5);
	objects_list->push_front(*elf2);
	//delete elf;
}

int main()
{
	
	objects_list = new list<gameobject>();
	events_list = new list<event_class>();
	gameRenderer = new renderer();
	gameRenderer->Initialize("Gus game", "icon.bmp");
	game_init(objects_list);
	Uint32 t = 0;
	const Uint32 dt = 10;
	Uint32 currentTime = SDL_GetTicks();
	Uint32 accumulator = 0;
	input_class *input = new input_class();
	SDL_EnableKeyRepeat(1, 0);
	while(!quit)
	{
		Uint32 newTime = SDL_GetTicks();
		Uint32 eventFrameTime = newTime - currentTime;
		currentTime = newTime;
		input->update(events_list);
		process_event();
		accumulator += eventFrameTime;
		while ( accumulator >= dt )
		{
			game_update(t, dt);
			accumulator -= dt;
			t += dt;
		}
		gameRenderer->RenderFrame(objects_list, current_map);
	}
	return 0;
}